/* eslint-disable @typescript-eslint/no-use-before-define */
import ROBOT_AVATAR from '@/assets/image/avatar_robo.png';
import { addGoodArticle } from '@/services/ant-design-pro/brainSpace';
import {
  dialogVersions,
  generateDialog,
  getSessionDetail,
  stopSession,
  structuringWrite,
  updateSession,
} from '@/services/ant-design-pro/dialog';
import { getDocumentsDetail } from '@/services/ant-design-pro/documents';
import { freeSession } from '@/services/ant-design-pro/highClassWrite';
import { isNotEmpty } from '@/utils/index';
import { DownOutlined, SaveOutlined, UpOutlined } from '@ant-design/icons';
import { Button, message } from 'antd';
import { nanoid } from 'nanoid';
import { parse } from 'querystring';
import React, { useEffect, useRef, useState } from 'react';
import { flushSync } from 'react-dom';
import { connect, history, useLocation } from 'umi';
import ArticleOutline from './com/articleOutline';
import Command from './com/command';
import Progress from './com/progress';
import ReferenceSpace from './com/referenceSpace';
import Version from './com/version';
import WriteCom from './com/writeCom';
import WriteTab from './com/writeTab';
import './index.less';
let interval: any = null;

const HighClassWrite: React.FC = ({ dispatch, highClassWrite }) => {
  const [isSlide, setIsSlide] = useState(false); //允许上滑或者下拉 在页面初始化时先不添加上滑的样式
  const [slide, setSlide] = useState(false); //上滑或者下拉
  const [session, setSession] = useState<any>(null);
  const [isExpend, setIsExpend] = useState<boolean>(false); //右侧展开收起
  const [selItemIndex, setSelItemIndex] = useState<number>(2); //右侧选中的功能
  const progressInfo = useRef<any>(null);
  const [pollingReqState, setPollingReqState] = useState<any>([]); //轮询请求的状态列表
  const [showProgress, setShowProgress] = useState<boolean>(false); //是否显示进度条 由轮询的状态决定
  const versionRef = useRef(null);
  const commandRef = useRef(null);
  const ArticleOutlineRef = useRef(null);
  const ReferenceSpaceRef = useRef(null);

  const {
    selVersionNo,
    documentUUID,
    curDoc,
    docList,
    robotLoading,
    writing_session_id,
    writing_type_id,
  } = highClassWrite;
  //公共更新model的方法
  const updateState = (updateObj: any) => {
    dispatch({
      type: 'highClassWrite/updateState',
      payload: updateObj,
    });
  };

  //设置当前文章选中的版本
  const setVersionNo = async (versionNo: number) => {
    updateState({
      selVersionNo: versionNo,
    });
    //获取文档详情
    getDetailData(documentUUID, versionNo);
  };

  //最右侧按钮点击
  const selectItem = (index: number) => {
    if (index === 1) {
      message.open({
        type: 'info',
        content: '参考功能正在搭建中，一起期待吧',
      });
      return;
    }
    //当前点击和之前选中的是同一个
    if (selItemIndex === index) {
      if (index === 2) {
        setIsExpend(!isExpend);
      } else if (index === 3) {
        setIsExpend(!isExpend);
      }
    } else {
      setIsExpend(false);
      setSelItemIndex(index);
    }
  };

  // 获取文档详情
  const getDetailData = async (id: string, version: number) => {
    let params: any = { id };
    if (version > 0) {
      params.version_no = version;
    }
    const res = await getDocumentsDetail(params);
    if (res.code === 0) {
      //将当前文档的内容 标题 和反馈情况存到model里
      if (res.data && res.data.feedbacks) {
        updateState({
          user_score: res.data.user_score,
          curFeedbacks: res.data.feedbacks,
          curDoc: {
            title: res.data.title,
            content: res.data.system_output,
            id: res.data.id,
          },
          standard_score: res.data.standard_score,
        });
      }
    }
  };

  const location = useLocation();
  const locationParam: any = parse(location.search.replace('?', ''));
  //创建sessionId
  const createSessionId = async () => {
    let res = await freeSession();
    console.log(res);
    if (res.code === 0) {
      updateState({
        writing_session_id: res?.data?.write_session_id,
        writing_type_id: res?.data?.writing_type_id,
      });
      //将write_session_id 添加到location的参数上
      window.history.replaceState(
        null,
        '',
        `${location.search}&writing_session_id=${res?.data?.write_session_id}`,
      );
    }
  };
  //页面初始化
  useEffect(() => {
    //如果url上有参数
    if (locationParam && locationParam.writing_session_id) {
      //如果页面上有writing_session_id 表示 1.从我的文档进入 2.从生成类型后进入
      sessionInfo(locationParam.writing_session_id); //根据sessionId获取到当前会话的信息
      updateState({
        writing_session_id: locationParam.writing_session_id,
        writing_type_id: locationParam.writing_type_id,
      });
    } else {
      //创建一个新的sessionId
      createSessionId();
    }
  }, []);

  //开始轮询
  const sessionInfo = async (sessionUUID: any, reset: boolean = false) => {
    const func = async () => {
      const status = await getSessionInfo(sessionUUID, reset); //查询当前会话的详细信息 根据状态判断
      //CREATED 或 IN_PROCESS 表示后台还在生成文章 会一直轮询 直至SUCCEED成功
      //SUCCEED 后台文章已全部生成完成
      //FAILED 或 DELETED 提示 文章生成失败，请重新生成!
      //CANCELED 提示 已取消文章生成
      if (status.status === 'CREATED' || status.status === 'IN_PROCESS') {
        // 继续处理
        updateState({
          robotLoading: true,
        });
      } else {
        clearInterval(interval);
        updateState({
          robotLoading: false,
        });
      }
    };

    func();
    if (interval) clearInterval(interval);
    interval = setInterval(func, 5000); // 10秒拉取一次
  };

  //根据sessionId调用接口 获取到当前会话的信息
  const getSessionInfo = async (sessionUUID: any, reset: boolean = false) => {
    const res = await getSessionDetail(sessionUUID); //查询单个会话
    if (res.code === 0) {
      let {
        status,
        key_points,
        user_input,
        click_status,
        example_details,
        leading_details,
        articles_expected,
        articles_generated,
        articles_selected,
        estimated_time,
      } = res.data;
      //在第一次请求时传入进度条组件需要的参数
      if (status !== 'INITED') {
        if (pollingReqState.length === 0 || reset) {
          //设置进度条需要的参数
          progressInfo.current = {
            articles_expected,
            articles_generated,
            articles_selected,
            estimated_time: estimated_time < 10 ? 13 : estimated_time,
          };
          setIsSlide(true);
          setSlide(true);
        }
      }
      setPollingReqState((prev: any) => [...prev, status]); //将轮询请求返回的状态保存起来 传递给进度条组件
      //存储文章公共信息
      updateState({
        articles_expected: articles_expected,
        docCommonInfo: {
          example_details: example_details, //例句
          key_points: key_points, //关键点
          leading_details: leading_details, //引导语 tag
          click_status: click_status, //是否点击过示例
          user_input: user_input,
        },
      });
      if (status === 'SUCCEED') {
        //在页面初始化后 的 轮询接口成功后才会添加文案
        if (reset && commandRef.current) {
          let systemTxtRecover = {
            key: nanoid(),
            type: 'systemTxtRecover',
            spend: 15,
            data: ['全部文章已生成'],
          };
          commandRef?.current?.setAILogs((prev) => [...prev, systemTxtRecover]);
        }

        const sessionRes = { ...res.data };
        sessionRes.writing_session_id = sessionRes.id;
        setSession(sessionRes);
        let { documents, id, last_document_id } = res.data; //当前会话的行文结构列表
        updateState({
          docList: documents, //当前会话的行文结构列表
        });
        //根据最后点击的文章id 回显最后选中的文章
        if (documents.length > 0) {
          let firstDocument = documents[0].documents[0]; //默认当前展示 第一个行文结构下的第一篇文章
          let find = false;
          documents.forEach((document: any) => {
            if (!find) {
              for (let index = 0; index < document.documents.length; index++) {
                const item = document.documents[index];
                //当前展示的文章 = 用户最后一次操作的文章
                if (item.document_id === last_document_id) {
                  //更新当前文章的总索引数
                  updateState({
                    currentDocIndex: item.doc_no,
                  });
                  firstDocument = item;
                  find = true;
                  break;
                }
              }
            }
          });
          //last_document_id不在返回的doc列表里 设置第一篇文章的id为last_document_id
          if (!find) {
            const params = {
              sessionId: id,
              currentDocIndex: firstDocument.doc_no,
              last_document_id: firstDocument.document_id,
            };
            updateSession(params);
            last_document_id = firstDocument.document_id;
          }
          const { version_no } = firstDocument.current_document_version;
          //将最后显示文章的id 文章的uuid 当前文章选中的版本号 存到公共状态
          updateState({
            last_document_id: last_document_id,
            documentUUID: firstDocument.document_uuid,
            selVersionNo: version_no,
          });
          //获取当前文章的版本列表
          getVersions(firstDocument.document_uuid);
          //根据文章uuid 版本号 获取当前要展示的文章内容 打分 点赞点踩数据
          getDetailData(firstDocument.document_uuid, version_no);
          setIsSlide(true);
          setSlide(true);
        }
      } else if (status === 'FAILED' || status === 'DELETED') {
        message.open({
          type: 'error',
          content: '文章生成失败，请重新生成!',
        });
        setShowProgress(false);
        setTimeout(() => {
          history.replace(`/conversationInit`);
        }, 500);
      } else if (status === 'CANCELED') {
        message.open({
          type: 'error',
          content: '已取消文章生成',
        });
        setShowProgress(false);
        setTimeout(() => {
          history.replace(`/conversationInit`);
        }, 500);
      }
      return {
        status,
      };
    } else {
      message.open({
        type: 'error',
        content: res.msg,
      });
      return { status: 'FAILED', totalCount: 0 };
    }
  };

  //tab选中左侧文档
  const selectDocument = (document: any) => {
    const { document_id, document_uuid, current_version_no } = document;
    console.log(document);

    //更新公共状态里的文章uuid 最后点击的文章id
    updateState({
      documentUUID: document.document_uuid,
      last_document_id: document_id,
    });
    // 重新获取当前文章的内容 评分 点赞和点踩数据
    getDetailData(document_uuid, current_version_no);
    // 重新获取当前文章的版本列表数据
    getVersions(document_uuid);
    //调用接口 更新last_document_id到后台
    const params = {
      sessionId: session.writing_session_id,
      last_document_id: document_id,
    };
    updateSession(params);

    //更新当前文章的总索引
    updateState({
      currentDocIndex: document.doc_no,
    });
  };

  //获取版本列表数据
  const getVersions = async (uuid: string) => {
    //调用versionRef的内部方法
    if (versionRef.current) {
      versionRef.current.initCheck();
    }
    //清空版本列表数据
    updateState({
      versions: [],
    });
    const res = await dialogVersions({ page: 1, per_page: 100, document_uuid: uuid });
    if (res.code === 0) {
      //更新用户输入的指令历史
      updateState({
        versions: res.data.versions || [],
        userCommands: res.data.user_commands.reverse(),
      });
    } else {
      message.open({
        type: 'error',
        content: res.msg,
      });
    }
  };

  //生成文章接口 在用户发送指令之后调用
  const generate = async (contentKey: any) => {
    let keyword = contentKey;

    if (!isNotEmpty(keyword)) {
      message.open({
        type: 'info',
        content: '请输入你的指令',
      });
      return;
    }
    updateState({
      robotLoading: true,
    });
    let params = {
      reference: '',
      last_system_output: curDoc?.content || '',
      current_user_command: keyword,
      command_identifier: nanoid(),
      selected_version_no: selVersionNo,
      document_uuid: documentUUID,
    };

    try {
      //重新生成文章内容
      const res = await generateDialog(params);
      if (res.code === 0) {
        const { document_uuid, version_no } = res.data;
        flushSync(() => {
          //更新当前文章uuid和版本
          updateState({
            documentUUID: document_uuid,
            selVersionNo: version_no,
          });
        });
        const sessionCopy = { ...session };
        //更新文章列表里 当前文章的最新版本
        sessionCopy.documents.forEach((document: any) => {
          document.documents.forEach((item: any) => {
            if (item.document_uuid === document_uuid) {
              item.current_version_no = version_no;
            }
          });
        });
        setSession(sessionCopy);
        updateState({
          docList: sessionCopy.documents,
        });
        //重新获取 版本列表数据
        getVersions(document_uuid);
      } else {
        message.open({
          type: 'error',
          content: res.msg,
        });
      }
    } catch (error) {
      console.log(error);
    }
    updateState({
      robotLoading: false,
    });
  };

  // 结构化推理，要点提炼之后调用
  const structWrite = async (articlesNum: number) => {
    if (robotLoading) return;
    setPollingReqState([]);
    updateState({
      robotLoading: true,
    });
    const params = {
      writing_type_id: writing_type_id,
      writing_session_id: writing_session_id,
      articles_total: articlesNum,
      key_points: [],
    };

    const res = await structuringWrite(params);
    if (res.code === 0) {
      setIsSlide(true);
      setSlide(true);
      setShowProgress(true);
      sessionInfo(params.writing_session_id, true);
    } else if (res.code === 20024) {
      updateState({
        robotLoading: false,
      });
      setShowProgress(false);
      //添加通用的系统文字回复类型
      let systemTxtRecover = {
        key: nanoid(),
        type: 'systemTxtRecover',
        data: ['没有关联的主题和大纲，请您先添加主题和大纲'],
      };
      commandRef?.current?.setAILogs((prev) => [...prev, systemTxtRecover]);
      let inspireIdeas = commandRef?.current?.highClassHandle?.find(
        (item) => item.type === 'inspireIdeas',
      );
      if (inspireIdeas) {
        setTimeout(() => {
          commandRef?.current?.toggleChilrenHandle(inspireIdeas);
        }, 1200);
      }
    } else {
      message.open({
        type: 'error',
        content: res.msg,
      });
      updateState({
        robotLoading: false,
      });
      setShowProgress(false);
    }
  };

  const stopStruct = async () => {
    const res = await stopSession(highClassWrite.writing_session_id);
    if (res.code === 0) {
      clearInterval(interval); //停止轮询
      setPollingReqState([]); //轮询请求状态数组清空
      setShowProgress(false); //隐藏进度条
      updateState({
        robotLoading: false,
      });
      message.open({
        type: 'info',
        content: '文章停止生成!',
      });
    } else {
      message.open({
        type: 'error',
        content: res.msg,
      });
    }
  };

  //保存到大脑空间
  const saveArticleSpace = async () => {
    let body: any = {
      subject: curDoc.title,
      main_body: curDoc.title, //文章内容
      tag: locationParam.type_name, //标签
      training_reason: '', //训练理由
      scope_class: 'MY_COLLECTION',
      document_version_id: curDoc.id,
    };

    let newFormData: any = new FormData();
    //将formObj的参数添加到newFormData里
    Object.keys(body).forEach((key) => {
      newFormData.append(key, body[key]);
    });
    //新增好文收藏
    let res = await addGoodArticle(newFormData);
    if (res.code === 0) {
      message.open({
        className: 'custom-saveArticleSpace',
        type: 'info',
        content: '文章已保存至AI大脑空间-好文收藏空间',
      });
    } else {
      message.open({
        type: 'error',
        content: res.msg,
      });
    }
  };
  //进入大脑空间
  const goArticleSpace = async () => {
    history.push('/spaceHome');
  };
  //头部添加 评价文档 保存至知识库 下载文档 三个按钮
  useEffect(() => {
    dispatch({
      type: 'headerModel/changeTitle',
      payload: locationParam.type_name,
    });
  }, []);
  //在数据更新的时候 更新方法的数据
  useEffect(() => {
    if (curDoc) {
      dispatch({
        type: 'headerModel/updateRightCon',
        payload: (
          <div style={{ marginRight: 10 }}>
            <Button
              type="text"
              size="small"
              style={{ margin: '0 10px' }}
              icon={<SaveOutlined />}
              onClick={() => {
                saveArticleSpace();
              }}
            >
              保存至大脑空间
            </Button>
            <div className="enterBrainSpaceBtnBox">
              <img className="" src={ROBOT_AVATAR} height={28} width={28} />
              <Button
                type="text"
                size="small"
                style={{ margin: '0 10px' }}
                onClick={() => {
                  goArticleSpace();
                }}
              >
                进入AI大脑空间
              </Button>
            </div>
          </div>
        ),
      });
    }
  }, [curDoc]);
  //在页面跳转之前清除定时器
  useEffect(() => {
    const handleBeforeUnload = () => {
      clearInterval(interval);
      //重置数据
      // updateState({
      //   userCommands: [],
      // });
      dispatch({
        type: 'highClassWrite/resetState',
      });
    };
    const unlisten = history.listen(() => {
      handleBeforeUnload();
    });
    return () => {
      unlisten();
      handleBeforeUnload();
    };
  }, []);
  //进度条动画
  useEffect(() => {
    //如果第一个请求状态不是成功才出现进度条
    if (
      progressInfo.current &&
      pollingReqState &&
      pollingReqState.length > 0 &&
      pollingReqState[0] !== 'SUCCEED'
    ) {
      setShowProgress(true);
    } else {
      setShowProgress(false);
    }
  }, [pollingReqState, progressInfo.current]);
  //上滑下拉
  const togglehighClassSlide = (state = true) => {
    setIsSlide(true);
    setSlide(state);
  };
  //选择篇数确定
  const generateSubmit = (data: any) => {
    //结构化推理接口
    structWrite(data);
  };

  //触发参考内容更新
  const triggerReference = (data: any) => {
    console.log('触发参考内容更新', data);

    ReferenceSpaceRef?.current?.updateData(data);
  };
  //触发大纲更新
  const triggerArticleMain = async (data: any) => {
    let res = await ArticleOutlineRef?.current?.updateData(data);
    //触发大纲更新回调
    if (res.code === 0) {
      let systemTxtRecover = {
        key: nanoid(),
        type: 'systemTxtRecover',
        spend: 15,
        data: ['文章大纲已更新'],
      };
      commandRef?.current?.setAILogs((prev) => [...prev, systemTxtRecover]);
    }
  };

  return (
    <div className="highClassWrap">
      <div className="highClassSectionLeftWrap">
        <div
          className={`ReferenceSpaceArticleOutlineWrap ${
            isSlide ? (slide ? 'highClassSlideUp' : 'highClassSlideUp2') : ''
          }`}
        >
          <ReferenceSpace
            ref={ReferenceSpaceRef}
            triggerArticleMain={triggerArticleMain}
          ></ReferenceSpace>
          <ArticleOutline ref={ArticleOutlineRef}></ArticleOutline>
          <div className="slideBtnWrap">
            {slide ? (
              <Button
                shape="circle"
                onClick={() => togglehighClassSlide(false)}
                icon={<DownOutlined />}
              />
            ) : (
              <Button
                shape="circle"
                onClick={() => togglehighClassSlide(true)}
                icon={<UpOutlined />}
              />
            )}
          </div>
        </div>
        <div
          className={`highClassSectionLeft ${
            isSlide ? (slide ? 'highClassSlideDown' : 'highClassSlideDown2') : ''
          }`}
        >
          {showProgress ? (
            <Progress
              progressInfo={progressInfo.current}
              pollingReqState={pollingReqState}
              setShowProgress={setShowProgress}
            ></Progress>
          ) : (
            <></>
          )}
          {docList && docList.length > 0 && <WriteTab selectDocument={selectDocument}></WriteTab>}
          <WriteCom
            setVersionNo={setVersionNo}
            getVersions={getVersions}
            selectItem={selectItem}
          ></WriteCom>
        </div>
      </div>
      <div className={'highClassSectionRight' + ' ' + (isExpend ? 'expend' : 'collapse')}>
        <Command
          ref={commandRef}
          visible={selItemIndex === 2}
          stopStruct={stopStruct}
          structWrite={structWrite}
          generate={generate}
          showProgress={showProgress}
          pollingReqState={pollingReqState}
          generateSubmit={generateSubmit}
          triggerReference={triggerReference}
          triggerArticleMain={triggerArticleMain}
        ></Command>
        <Version
          ref={versionRef}
          visible={selItemIndex === 3}
          setVersionNo={setVersionNo}
        ></Version>
      </div>
      <div
        className={'topRightRobotBox scan-effect ' + ' ' + (isExpend ? 'scaleMin' : '')}
        onClick={() => selectItem(2)}
      >
        <img className="avatar image-to-flash" src={ROBOT_AVATAR} height={42} width={40} />
        <div className="scan-line"></div>
      </div>
    </div>
  );
};

export default connect(({ headerModel, highClassWrite }) => ({ headerModel, highClassWrite }))(
  HighClassWrite,
);
